/*
 * @Author: zhaiyujia
 * @Date: 2022-11-23 14:26:20
 * @LastEditors: zhaiyujia
 * @LastEditTime: 2022-11-24 03:18:40
 * @Description: file content
 */

#include "Arduino.h"

// 调色盘基础色
long base[7][3] = {
    {0x00, 0xff, 0x00},
    {0x00, 0xff, 0xff},
    {0x00, 0x00, 0xff},
    {0xff, 0x00, 0xff},
    {0xff, 0x00, 0x00},
    {0xff, 0xff, 0x00},
    {0x00, 0xff, 0x00}};

typedef struct
{
    uint8_t g;
    uint8_t r;
    uint8_t b;
} color_def;

// id 色表索引, grids 色表总格数
color_def getColor(uint8_t id, uint8_t grids)
{
    uint8_t rows = grids / 6;             // 每阶变换次数
    uint8_t level = id / rows;            // 需要获取的颜色处于那一阶
    uint8_t level_id = id - level * rows; // 需要获取的颜色处于当前阶的第几格
    color_def color;
    color.g = base[level][0] + (base[level + 1][0] - base[level][0]) / rows * level_id; // 阶的起始色+阶的渐变色
    color.r = base[level][1] + (base[level + 1][1] - base[level][1]) / rows * level_id; // 阶的起始色+阶的渐变色
    color.b = base[level][2] + (base[level + 1][2] - base[level][2]) / rows * level_id; // 阶的起始色+阶的渐变色
    // Serial_printf("id=%2u,ch.e=%u,le.l=%2u,le.d%3u>>%4u|%4u|%4u\r\n", (uint16_t)id, (uint16_t)rows, (uint16_t)level, (uint16_t)level_id, (uint16_t)color.g, (uint16_t)color.r, (uint16_t)color.b);
    return color;
}

// 创建色表
void rainbowColor(uint8_t *leds, uint8_t count, uint8_t brightness)
{
    uint8_t i;
    for (i = 0; i < count * 3; i += 3)
    {
        color_def color;
        color = getColor(i / 3, 18);
        leds[i] = color.g * (brightness / 255.0);
        leds[i + 1] = color.r * (brightness / 255.0);
        leds[i + 2] = color.b * (brightness / 255.0);
    }
}

#if 0 // RGB <--> HSV
struct RGB
{
    unsigned char R;
    unsigned char G;
    unsigned char B;
};

struct HSV
{
    double H;
    double S;
    double V;
};

struct RGB HSVToRGB(struct HSV hsv)
{
    double r = 0, g = 0, b = 0;
    struct RGB rgb;

    if (hsv.S == 0)
    {
        r = hsv.V;
        g = hsv.V;
        b = hsv.V;
    }
    else
    {
        int i;
        double f, p, q, t;

        if (hsv.H == 360)
            hsv.H = 0;
        else
            hsv.H = hsv.H / 60;

        i = (int)(hsv.H);
        f = hsv.H - i;

        p = hsv.V * (1.0 - hsv.S);
        q = hsv.V * (1.0 - (hsv.S * f));
        t = hsv.V * (1.0 - (hsv.S * (1.0 - f)));

        switch (i)
        {
        case 0:
            r = hsv.V;
            g = t;
            b = p;
            break;

        case 1:
            r = q;
            g = hsv.V;
            b = p;
            break;

        case 2:
            r = p;
            g = hsv.V;
            b = t;
            break;

        case 3:
            r = p;
            g = q;
            b = hsv.V;
            break;

        case 4:
            r = t;
            g = p;
            b = hsv.V;
            break;

        default:
            r = hsv.V;
            g = p;
            b = q;
            break;
        }
    }

    rgb.R = r * 255;
    rgb.G = g * 255;
    rgb.B = b * 255;

    return rgb;
}

static double Min(double a, double b)
{
    return a <= b ? a : b;
}

static double Max(double a, double b)
{
    return a >= b ? a : b;
}

struct HSV RGBToHSV(struct RGB rgb)
{
    double delta, min;
    double h = 0, s, v;
    struct HSV hsv;

    min = Min(Min(rgb.R, rgb.G), rgb.B);
    v = Max(Max(rgb.R, rgb.G), rgb.B);
    delta = v - min;

    if (v == 0.0)
        s = 0;
    else
        s = delta / v;

    if (s == 0)
        h = 0.0;

    else
    {
        if (rgb.R == v)
            h = (rgb.G - rgb.B) / delta;
        else if (rgb.G == v)
            h = 2 + (rgb.B - rgb.R) / delta;
        else if (rgb.B == v)
            h = 4 + (rgb.R - rgb.G) / delta;

        h *= 60;

        if (h < 0.0)
            h = h + 360;
    }

    hsv.H = h;
    hsv.S = s;
    hsv.V = v / 255;

    return hsv;
}

// R: 87 G: 153 B: 124
void test1()
{
    struct HSV dat = {154, 0.43, 0.60};
    struct RGB value;
    value = HSVToRGB(dat);
    Serial_printf("%u,%u,%u,\r\n", (uint16_t)value.R, (uint16_t)value.G, (uint16_t)value.B);
}

// H: 296.55172413793105 S: 1 V: 0.3411764705882353
void test2()
{
    struct RGB dat = {82, 0, 87};
    struct HSV value;
    value = RGBToHSV(dat);
    Serial_printf("%f,%f,%f,\r\n", value.H, value.S, value.V);
}
#endif